﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web.Mvc;
using EzDesk.Utility.Extensions;
using EzDesk.Utility.Web.Extensions;
using EzDesk.Utility.Web.Controllers;
using EzDesk.Apps.Model.Attendance;
using EzDesk.Utility;
using EzDesk.Clients.DesktopWeb.Attendance.ViewModel;
using EzDesk.Utility.Log;
using EzDesk.Clients.DesktopWeb.AttendanceService;
using EzDesk.Utility.Web.ServiceReference;
using EzDesk.Utility.ServiceStatusInfo;

namespace EzDesk.Clients.DesktopWeb.Controllers
{
    [Authorize]
    public class AttendanceController : EzDeskAppController
    {
        static IAttendanceService AttendanceService
        {
            get { return ServiceReferenceFactory<IAttendanceService, AttendanceServiceClient>.GetService(); }
        }

        #region [ Page Method ]
        //
        // GET: /Attendance/CheckAttendance

        [Authorize]
        public ActionResult CheckAttendance(string state, string info)
        {
            var currentTime = DateTime.Now;
            var attendanceConfig = AttendanceService.GetAttendanceConfig().Result;

            var ondutyTimeForward = attendanceConfig.StdOnDutyTime.ToDateTime() - attendanceConfig.OnDutyOffsetForward;
            var ondutyTimeDelay = attendanceConfig.StdOnDutyTime.ToDateTime() + attendanceConfig.StdOnDutyTimeDelay;
            var offdutyTimeForward = attendanceConfig.StdOffDutyTime.ToDateTime() - attendanceConfig.OnDutyOffsetForward;
            var offdutyTimeDelay = attendanceConfig.StdOffDutyTime.ToDateTime() + attendanceConfig.StdOnDutyTimeDelay;

            var attendanceConfigModel = new
                                            {
                                                ondutyTimeForward = ondutyTimeForward.ToShortTimeString(),
                                                ondutyTimeDelay = ondutyTimeDelay.ToShortTimeString(),
                                                offdutyTimeForward = offdutyTimeForward.ToShortTimeString(),
                                                offdutyTimeDelay = offdutyTimeDelay.ToShortTimeString(),
                                            };

            var currentDefaultAtendanceType = getDefaultAttendanceStatus();

            ViewData["AttendanceConfig"] = attendanceConfigModel.ToJson();
            ViewData["IsAbnormal"] = currentDefaultAtendanceType.IsAbnormal ? "true" : "false";
            ViewData["IsDuplicated"] = currentDefaultAtendanceType.IsDuplicated ? "true" : "false";
            ViewData["CurrentDefaultAttendance"] = currentDefaultAtendanceType.AttendanceType;
            ViewData["DayInfo"] = AttendanceService.GetDayInfo(CurrentUserId, currentTime).Result.ToJson();

            ViewData["CurrentTime"] = getEpochForJavascript(currentTime);
            ViewData["CurrentUser"] = EzApiClient.GetSimpleUserById(CurrentUserId).ToJson();

            return View();
        }


        //
        // GET: /Attendance/ApplyLeave

        [Authorize]
        [HttpGet]
        public ActionResult ApplyLeave()
        {
            ViewData["LeaveTypeList"] = AttendanceService.GetAllLeaveTypes().Result.ToJson();
            ViewData["CurrentTime"] = getEpochForJavascript(DateTime.Now);
            ViewData["UserId"] = CurrentUserId.ToString();
            return View();
        }

        //
        // GET: /Attendance/PersonalAttendanceList

        [Authorize]
        [HttpGet]
        public ActionResult AttendanceInfoListPerMonth(long? time, Guid? userId)
        {
            DateTime date = getDateByDefault(time);

            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }
            var currentUser = EzApiClient.GetSimpleUserById(userId.GetValueOrDefault());


            var permissionStr = "ATTENDANCE_HR_MANAGEMENT";
            var isHasPermisson = IsHasPermisson(permissionStr, userId.Value);
            LogEx.TRACE("DesktopWeb - Attendance",
                        "IsHasPermission: " + permissionStr + " " + userId.Value + " " + isHasPermisson.ToString());

            ViewData["IsHasPermisson"] = isHasPermisson.ToJson();
            ViewData["StartYear"] = "2009";
            ViewData["TargetTime"] = getEpochForJavascript(date);
            ViewData["CurrentTime"] = getEpochForJavascript(DateTime.Now);
            ViewData["CurrentDeptList"] = EzApiClient.GetAllDepts().ToJson();
            ViewData["CurrentUser"] = currentUser.ToJson();
            return View();
        }

        //
        // GET: /Attendance/PersonalLeaveInfoList

        [Authorize]
        public ActionResult PersonalLeaveInfoList(long? time, Guid? userId)
        {
            DateTime date = getDateByDefault(time);
            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }
            var currentUser = EzApiClient.GetSimpleUserById(userId.GetValueOrDefault());

            var permissionStr = "ATTENDANCE_HR_MANAGEMENT";
            var isHasPermisson = IsHasPermisson(permissionStr, (Guid)userId);

            ViewData["IsHasPermisson"] = isHasPermisson.ToJson();
            ViewData["CurrentTime"] = getEpochForJavascript(date);
            ViewData["CurrentDeptList"] = EzApiClient.GetAllDepts().ToJson();
            ViewData["CurrentUser"] = currentUser.ToJson();

            return View();
        }

        //
        // GET: /Attendance/AuditLeave
        [Authorize]
        [PermissionRequireAttribute("ATTENDANCE_HR_MANAGEMENT")]
        public ActionResult AuditLeave(Guid leaveId, bool? isAgree, string target)
        {
            // 处理直接审批
            if (target == "action")
            {
                return DoAuditLeave(leaveId, isAgree.GetValueOrDefault(false), "");
            }

            LeaveInfo leaveInfo = AttendanceService.GetLeaveInfoById(leaveId).Result;
            ViewData["LeaveInfo"] = leaveInfo.ToJson();

            return View();
        }

        //
        // GET: /Attendance/AuditList
        [Authorize]
        [HttpGet]
        [PermissionRequireAttribute("ATTENDANCE_HR_MANAGEMENT")]
        public ActionResult AuditList()
        {
            ViewData["StartYear"] = "2009";
            ViewData["CurrentTime"] = getEpochForJavascript(DateTime.Now);
            ViewData["CurrentUser"] = EzApiClient.GetSimpleUserById(CurrentUserId).ToJson();

            return View();
        }


        /// <summary>
        /// 人事查看某日考勤情况汇总页面
        /// </summary>
        /// <param name="time">要显示页面的时间</param>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        [PermissionRequireAttribute("ATTENDANCE_HR_MANAGEMENT")]
        public ActionResult AttendanceInfoListPerDayManager(long? time)
        {
            LogEx.TRACE("DesktopClient - Attendance", "开始AttendanceInfoListPerDayManager请求");
            var isDisplayEvaluationInfo = "true";
            var isDisplayAttendanceInfo = "false";
            // 获取页面要显示的内容日期
            DateTime date = getDateByDefault(time);

            // 获取当日的dayInfo
            var dayInfo = AttendanceService.GetDayInfo(CurrentUserId, date).Result;

            // 获取当日所有员工的考勤详细情况
            var allUserList = EzApiClient.GetSimpleUserInfos("everyone");
            var dayAttendanceDetailList = allUserList.Select(
                user =>
                {
                    var attendanceEvaluation = AttendanceService.GetDayAttendanceEvaluation(user.Id, date).Result;
                    var applicationInfo = AttendanceService.GetCurrentEvaluationModifyApplication(user.Id, date).Result;
                    var application = (applicationInfo != null) ? "申请修改中" : "";
                    var attendanceInfoList = AttendanceService.GetAttendanceInfoListByUserInDay(date, user.Id, null).Result;
                    var leaveInfo = AttendanceService.GetDayLeaveInfo(user.Id, date).Result;
                    return new
                               {
                                   TargetUser = user,
                                   AttendanceEvaluation = attendanceEvaluation,
                                   AttendanceInfoList = attendanceInfoList,
                                   Application = application,
                                   LeaveInfo = leaveInfo,
                                   IsAbnormal = attendanceEvaluation.Manhours < 70 // todo: 封装 有问题的考勤的逻辑
                               };
                })
                .OrderByDescending(p => p.IsAbnormal)
                .ToList();

            //当日日期
            var currentDate = DateTime.Now.Date;
            //如果是当日不显示考勤评估信息
            if (currentDate == dayInfo.Date)
            {
                isDisplayEvaluationInfo = "false";
            }

            //非将来时间
            if (currentDate >= dayInfo.Date)
            {
                isDisplayAttendanceInfo = "true";

                ViewData["IsDisplayEvaluationInfo"] = isDisplayEvaluationInfo;
                ViewData["DayAttendanceDetailList"] = dayAttendanceDetailList.ToJson();
            }

            ViewData["DayInfo"] = dayInfo.ToJson();
            ViewData["IsDisplayAttendanceInfo"] = isDisplayAttendanceInfo;
            LogEx.TRACE("DesktopClient - Attendance", "返回AttendanceInfoListPerDayManager请求");
            return View();
        }



        /// <summary>
        /// 人事修改某日某人考勤情况页面
        /// </summary>
        /// <param name="time">要显示页面的时间</param>
        /// <param name="userId">目标用户的Id</param>
        /// <returns></returns>
        [Authorize]
        [PermissionRequireAttribute("ATTENDANCE_HR_MANAGEMENT")]
        public ActionResult ModifyAttendanceInfoPerDay(long? time, Guid userId)
        {
            // 获取页面要显示的内容日期
            DateTime date = getDateByDefault(time);

            // 获取当日dayInfo
            DayInfo dayInfo = AttendanceService.GetDayInfo(userId, date).Result;

            // 当日考勤详细信息
            var dayAttendanceDetail = new DayAttendanceInfoDetailModel()
            {
                TargetUser = EzApiClient.GetSimpleUserById(userId),
                AttendanceEvaluation =
                    AttendanceService.GetDayAttendanceEvaluation(userId, date).Result,
                AttendanceInfoList =
                    AttendanceService.GetAttendanceInfoListByUserInDay(date, userId,
                                                                        null).Result,
                LeaveInfo = AttendanceService.GetDayLeaveInfo(userId, date).Result
            };

            //当日日期
            var currentDate = DateTime.Now.Date;
            //处理当天的矿工
            if (currentDate == dayInfo.Date)
            {
                dayAttendanceDetail.AttendanceEvaluation.IsAbsense = false;
            }

            // 获取正在提交中的评估修改申请
            var modifyAttendanceApplication = AttendanceService.GetCurrentEvaluationModifyApplication(userId, date).Result;

            // 获得考勤评估修改的历史信息
            var evaluationModifyHistory = AttendanceService.GetEvaluationModifyHistory(userId, date).Result;



            ViewData["CurrentDate"] = getEpochForJavascript(currentDate);
            ViewData["ModifyAttendanceApplication"] = modifyAttendanceApplication.ToJson();
            ViewData["DayAttendanceDetail"] = dayAttendanceDetail.ToJson();
            ViewData["EvaluationModifyHistory"] = evaluationModifyHistory.ToJson();
            // 默认显示自己的信息
            ViewData["TargetUser"] = EzApiClient.GetSimpleUserById(userId).ToJson();
            ViewData["DayInfo"] = dayInfo.ToJson();

            return View();
        }

        /// <summary>
        /// 显示个人某一天的考勤情况
        /// </summary>
        /// <param name="time">要显示的时间，Epoch格式</param>
        /// <returns></returns>
        [Authorize]
        public ActionResult PersonalAttendanceInfoPerDay(long? time, bool? isApplying = false)
        {
            var userId = CurrentUserId;
            // 获取页面要显示的内容日期
            var date = getDateByDefault(time);
            //当日日期
            var currentDate = DateTime.Now.Date;

            //是否可以申请修改
            var isDisplayApplyEvaluation = "true";
            //是否显示考勤是信息
            var isDisplayAttendanceInfo = "false";
            //是否显示考勤的评估信息
            var isDisplayEvaluationInfo = "true";
            //是否正在申请
            var isApplyingModify = "false";
            if (isApplying == true)
            {
                isApplyingModify = "true";
            }
            // 获取当日dayInfo
            var dayInfo = AttendanceService.GetDayInfo(userId, date).Result;
            // 获取正在提交中的评估修改申请
            var modifyAttendanceApplication = AttendanceService.GetCurrentEvaluationModifyApplication(userId, date).Result;
            // 当日考勤详细信息
            var dayAttendanceDetail = new DayAttendanceInfoDetailModel()
            {
                TargetUser = EzApiClient.GetSimpleUserById(userId),
                AttendanceEvaluation =
                    AttendanceService.GetDayAttendanceEvaluation(userId, date).Result,
                AttendanceInfoList =
                    AttendanceService.GetAttendanceInfoListByUserInDay(date, userId,
                                                                        null).Result,
                LeaveInfo = AttendanceService.GetDayLeaveInfo(userId, date).Result
            };

            // 获得考勤评估修改的历史信息
            var evaluationModifyHistory = AttendanceService.GetEvaluationModifyHistory(userId, date).Result;


            //如果已经申请修改或者是当天,不可再次申请
            if (modifyAttendanceApplication != null || currentDate == dayInfo.Date)
            {
                isDisplayApplyEvaluation = "false";
            }

            //如果是当日不显示考勤评估信息
            if (currentDate == dayInfo.Date)
            {
                isDisplayEvaluationInfo = "false";
            }

            //非将来时间
            if (currentDate >= dayInfo.Date)
            {
                isDisplayAttendanceInfo = "true";
                //显示考勤先关信息
                ViewData["ModifyAttendanceApplication"] = modifyAttendanceApplication.ToJson();
                ViewData["DayAttendanceDetail"] = dayAttendanceDetail.ToJson();
                ViewData["EvaluationModifyHistory"] = evaluationModifyHistory.ToJson();
                ViewData["IsDisplayApplyEvaluation"] = isDisplayApplyEvaluation;
                ViewData["IsDisplayEvaluationInfo"] = isDisplayEvaluationInfo;
                ViewData["IsApplyingModify"] = isApplyingModify;
            }

            ViewData["IsDisplayAttendanceInfo"] = isDisplayAttendanceInfo;
            ViewData["DayInfo"] = dayInfo.ToJson();
            ViewData["TargetUser"] = EzApiClient.GetSimpleUserById(userId).ToJson();

            return View();
        }


        #endregion

        #region [ Ajax Methods ]

        //
        // POST: /Attendance/ApplyModifyAttendanceEvaluation
        /// <summary>
        /// 提交修改考勤评估的申请
        /// </summary>
        /// <returns></returns>
        [Authorize]
        public JsonResult ApplyModifyAttendanceEvaluation(
            Guid applyUserId,
            int date,
            string applyText
            )
        {
            var theDate = EpochDateTimeExtension.FromEpoch(date);
            var statusInfo = AttendanceService.ApplyEvaluationModify(
                applyUserId,
                theDate,
                applyText
                );
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = "考勤评估更改申请成功";
            }
            return Json(statusInfo);
        }

        // 
        // POST: /Attendance/ModifyAttendanceEvaluation
        /// <summary>
        /// 修改某人的考勤评估
        /// </summary>
        /// <param name="targetUserId"></param>
        /// <param name="date"></param>
        /// <param name="lateMiniutes"></param>
        /// <param name="leaveEarlyMiniutes"></param>
        /// <param name="isAbsense"></param>
        /// <param name="isExtraWork"></param>
        /// <param name="manHours"></param>
        /// <returns></returns>
        [Authorize]
        [HttpPost]
        public JsonResult ModifyAttendanceEvaluation(
            Guid targetUserId, int date,
            int? lateMiniutes,
            int? leaveEarlyMiniutes,
            bool? isAbsense,
            bool? isExtraWork,
            int? manHours
            )
        {
            var theDate = EpochDateTimeExtension.FromEpoch(date);
            var newEvaluation = AttendanceService.GetDayAttendanceEvaluation(targetUserId, theDate).Result;

            if (lateMiniutes != null)
            {
                newEvaluation.LateMiniutes = lateMiniutes.Value;
            }
            if (leaveEarlyMiniutes != null)
            {
                newEvaluation.EarlyMiniutes = leaveEarlyMiniutes.Value;
            }
            if (isAbsense != null)
            {
                newEvaluation.IsAbsense = isAbsense.Value;
            }
            if (isExtraWork != null)
            {
                newEvaluation.IsExtraWork = isExtraWork.Value;
            }
            if (manHours != null)
            {
                newEvaluation.Manhours = manHours.Value;
            }

            var statusInfo = AttendanceService.ModifyEvaluation(newEvaluation, CurrentUserId);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = "考勤评估修改完成";
            }
            return Json(statusInfo);
        }

        //POST: /Attendance/RejectEvaluationApplication
        public ActionResult RejectEvaluationApplication(Guid applicationId)
        {
            var statusInfo = AttendanceService.RejectEvaluationApplication(CurrentUserId, applicationId);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = "已经拒绝了该修改申请";
            }
            return Json(statusInfo, JsonRequestBehavior.AllowGet);
        }

        // GET: /Attendance/CurrentTimeFromServer

        /// <summary>
        /// 获得当前系统的服务端时间
        /// </summary>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public JsonResult CurrentTimeFromServer()
        {
            var currentTime = DateTime.Now.ToEpoch();

            return Json(
                new { CurrentTime = currentTime },
                JsonRequestBehavior.AllowGet
                );
        }

        //
        // GET: /Attendnace/CurrentDefaultAttendanceStatus

        /// <summary>
        /// 获取当前的合法考勤类型以及考勤状态
        /// </summary>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public JsonResult CurrentDefaultAttendanceStatus()
        {
            return Json(
               getDefaultAttendanceStatus(),
               JsonRequestBehavior.AllowGet
               );
        }


        //
        // GET: /Attendnace/AttendanceTypeStatus

        /// <summary>
        /// 传入一个考勤类型，获取当前时间考勤状态，包括是否非正常考勤，是否重复考勤等
        /// </summary>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public JsonResult AttendanceTypeStatus(string attendanceTypeStr)
        {
            var attendanceType = EnumExt.ParseEnum<AttendanceType>(attendanceTypeStr);
            var currentAttendanceType = AttendanceService.GetAttendanceStatus(CurrentUserId, DateTime.Now, attendanceType).Result;

            return Json(
                currentAttendanceType,
                JsonRequestBehavior.AllowGet
                );
        }

        //
        // GET: /Attendance/AttendanceList/

        /// <summary>
        /// 获取某一天中所有考勤人员的列表
        /// </summary>
        /// <param name="dutyType">考勤类型</param>
        /// <param name="dateEpoch">考勤日期的Epoch值</param>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public JsonResult AttendanceListPerDay(string attendanceTypeStr, int dateEpoch)
        {
            var attendanceType = EnumExt.ParseEnum<AttendanceType>(attendanceTypeStr);
            var date = EpochDateTimeExtension.FromEpoch(dateEpoch);

            var attendanceInfoList = AttendanceService.GetAttendanceInfoListByUsersInDay(
                date,
                attendanceType: attendanceType,
                userIdList: null
                ).Result.OrderByDescending(x => x.ActionTime)
                .ToList();

            return Json(
                new
                {
                    AttendanceInfoList = convertAttendanceInfoListToModel(attendanceInfoList)
                },
                JsonRequestBehavior.AllowGet
                );
        }

        //
        // GET: /Attendance/PersonalAttendanceListPerMonth

        /// <summary>
        /// 获得某人一个月内的考勤状况
        /// </summary>
        /// <param name="currentYear">要获得数据的年份</param>
        /// <param name="currentMonth">要获得数据的月份</param>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public JsonResult PersonalAttendanceListPerMonth(int currentYear, int currentMonth, Guid? userId)
        {
            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }
            // 提供 按日期的所有内容
            // 先得到这个月这个人的所有考勤记录
            var startDate = new DateTime(currentYear, currentMonth, 1);
            var endDate = startDate.AddMonths(1).AddDays(-1);

            var attendanceInfos = AttendanceService.GetAttendanceInfoListByUserBetweenDays(startDate, endDate, userId.GetValueOrDefault(), null).Result;
            var dayLeaveInfos = AttendanceService.GetDayLeaveInfos(userId.Value, startDate.Date, endDate.Date).Result;
            var dayInfos = AttendanceService.GetDayInfos(userId.Value, startDate.Date, endDate.Date).Result;
            var monthAttendanceInfoList = new List<dynamic>();

            foreach (var theDayInfo in dayInfos)
            {
                var dayAttendanceInfoList = new List<DayAttendanceInfoModel>();
                var theDay = theDayInfo.Date;
                if (theDay > DateTime.Now.Date) continue;
                //获得请假记录
                var theDayLeaveInfo = dayLeaveInfos.FirstOrDefault(p => p.Date == theDay);

                //正常考勤上班
                var dayOnDutyInfo = findAttendanceInfoFromList(attendanceInfos, theDay, AttendanceType.onDuty).SingleOrDefault();
                //正常考勤下班
                var dayOffDutyInfo = findAttendanceInfoFromList(attendanceInfos, theDay, AttendanceType.offDuty).SingleOrDefault();
                //非正常考勤上班
                var ondutyAbnorml = findAttendanceInfoFromList(attendanceInfos, theDay, AttendanceType.onDuty, true);
                //非正常考勤下班
                var offdutyAbnorml = findAttendanceInfoFromList(attendanceInfos, theDay, AttendanceType.offDuty, true);
                // 如果没有考勤记录，则建立空记录
                if (dayOnDutyInfo == null && ondutyAbnorml.Count == 0)
                {
                    dayOnDutyInfo = new DayAttendanceInfoModel(userId.Value, theDay, AttendanceType.onDuty);
                }
                if (dayOffDutyInfo == null && offdutyAbnorml.Count == 0)
                {
                    dayOffDutyInfo = new DayAttendanceInfoModel(userId.Value, theDay, AttendanceType.offDuty);
                }
                //增添已有的考勤记录
                if (dayOnDutyInfo != null) dayAttendanceInfoList.Add(dayOnDutyInfo);
                if (ondutyAbnorml != null) dayAttendanceInfoList.AddRange(ondutyAbnorml);
                if (dayOffDutyInfo != null) dayAttendanceInfoList.Add(dayOffDutyInfo);
                if (offdutyAbnorml != null) dayAttendanceInfoList.AddRange(offdutyAbnorml);
                //申请记录
                var applicationInfo = AttendanceService.GetCurrentEvaluationModifyApplication(userId.Value, theDay).Result;
                var application = (applicationInfo != null) ? "申请修改中" : "";
                //工时
                var manHours = AttendanceService.GetDayAttendanceEvaluation(userId.Value, theDay).Result.Manhours;

                var dayAttendanceInfoListTheDay = new
                {
                    theDayInfo,
                    theDayLeaveInfo,
                    dayAttendanceInfoList,
                    application,
                    manHours
                };


                monthAttendanceInfoList.Add(dayAttendanceInfoListTheDay);
            }

            return Json(
                monthAttendanceInfoList,
                JsonRequestBehavior.AllowGet
                );
        }


        /// <summary>
        /// 获取审批用的假期列表
        /// </summary>
        /// <param name="isShowAuditedLeave">是否包括出已经审核的假期</param>
        /// <param name="currentMonth">对于已审核的假期显示的月份</param>
        /// <param name="currentYear">对于已审核的假期显示的年份</param>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public ActionResult LeaveInfoListForAudit(bool isShowAuditedLeave, int? currentMonth, int? currentYear)
        {
            var startDate = DateTime.Now.AddYears(-1);
            var endDate = DateTime.Now;
            var result = new List<LeaveInfo>();
            // 先获得所有还没有审核的假期条目
            var notAuditedLeaveList = AttendanceService.GetLeaveInfoList(
                null,
                null,
                createTimeStart: startDate,
                createTimeEnd: endDate,
                userId: null,
                isAgreed: null,
                isAudited: false
                ).Result;
            result.AddRange(notAuditedLeaveList);

            // 如果需要，获得已经审核的假期条目
            if (isShowAuditedLeave)
            {
                if (!currentYear.HasValue)
                {
                    throw new Exception();
                }
                if (!currentMonth.HasValue)
                {
                    throw new Exception();
                }

                startDate = new DateTime(currentYear.Value, currentMonth.Value, 1);
                endDate = startDate.AddMonths(1).AddDays(-1);
                var auditedLeaveList = AttendanceService.GetLeaveInfoList(
                    null,
                    null,
                    createTimeStart: startDate,
                    createTimeEnd: endDate,
                    userId: null,
                    isAgreed: null,
                    isAudited: null
                    ).Result;
                result = auditedLeaveList;
            }

            return Json(
                result,
                JsonRequestBehavior.AllowGet
                );
        }

        // 
        // GET: /Attendance/LeaveInfoById
        [HttpGet]
        public JsonResult LeaveInfoById(Guid leaveId)
        {
            var leaveInfo = AttendanceService.GetLeaveInfoById(leaveId).Result;
            return Json(
                leaveInfo,
                JsonRequestBehavior.AllowGet
                );
        }

        //
        // GET: /Attendance/PersonalLeaveInfoListPerYear
        [HttpGet]
        public JsonResult PersonalLeaveInfoListPerYear(int currentDate, Guid? userId)
        {
            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }
            var date = EpochDateTimeExtension.FromEpoch(currentDate);
            var startTime = new DateTime(date.Year, 1, 1);
            var endTime = new DateTime(date.Year + 1, 1, 1).AddHours(-1);

            // 返回所有审核已通过 或者 未审核 的记录
            var leaveInfoList = AttendanceService.GetLeaveInfoList(
                startTime, endTime,
                createTimeStart: null,
                createTimeEnd: null,
                userId: userId,
                isAudited: null,
                isAgreed: null
                ).Result;

            return Json(
                convertLeaveInfoListToSimpleModel(leaveInfoList),
                JsonRequestBehavior.AllowGet
                );
        }


        [HttpGet]
        public ActionResult PersonalAttendanceInfoList(long? time, Guid? userId)
        {
            var date = getDateByDefault(time);
            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }
            var currentUser = EzApiClient.GetSimpleUserById(userId.GetValueOrDefault());

            const string permissionStr = "ATTENDANCE_HR_MANAGEMENT";
            var isHasPermisson = IsHasPermisson(permissionStr, (Guid)userId);

            ViewData["IsHasPermisson"] = isHasPermisson.ToJson();
            ViewData["CurrentTime"] = getEpochForJavascript(date);
            ViewData["CurrentDeptList"] = EzApiClient.GetAllDepts().ToJson();
            ViewData["CurrentUser"] = currentUser.ToJson();

            return View();
        }

        /// <summary>
        /// 员工查看个人一年考勤情况
        /// </summary>
        /// <param name="time"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        [HttpGet]
        public JsonResult PersonalAttendanceInfoListPerMonth(int time, Guid? userId)
        {
            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }

            var date = EpochDateTimeExtension.FromEpoch(time);
            var month = date.Month;
            var year = date.Year;
            var startDate = new DateTime(year, month, 1);
            var endDate = startDate.AddMonths(1).AddDays(-1);

            var monthAttendanceInfoList = new List<dynamic>();
            //日历数据
            var infoForCalendarList = new List<dynamic>();
            //每天的考勤详情
            var attendanceInfoPerDayList = new List<dynamic>();


            var attendanceInfos =
                AttendanceService.GetAttendanceInfoListByUserBetweenDays(startDate.Date, endDate.Date, userId.Value,
                                                                         null).Result;
            var leaveInfos = AttendanceService.GetDayLeaveInfos(userId.Value, startDate.Date, endDate.Date).Result;
            var attendanceEvaluations = AttendanceService.GetDayAttendanceEvaluations(userId.Value, startDate.Date, endDate.Date).Result;
            var modifyAttendanceApplications = AttendanceService.GetCurrentEvaluationModifyApplications(userId.Value, startDate.Date, endDate.Date).Result;
            var dayInfos = AttendanceService.GetDayInfos(userId.Value, startDate.Date, endDate.Date).Result;

            foreach (var theDayInfo in dayInfos)
            {
                var theDay = theDayInfo.Date;
                //将来时间
                if (theDay > DateTime.Now) continue;
                //考勤记录
                var attendanceInfoList = attendanceInfos.Where(p => p.Date == theDay);
                //假期
                var leaveInfoList = leaveInfos.FirstOrDefault(p => p.Date == theDay);
                var leaveInfoModel = new List<dynamic>();
                if (leaveInfoList.Leaves.Count > 0)
                {
                    leaveInfoModel.AddRange(
                        leaveInfoList.Leaves.Select(
                            leave => new
                            {
                                leave.StartTime,
                                leave.EndTime,
                                leave.LeaveTypeName
                            }));
                }

                var isAbnormal = false;
                //考勤评估
                var attendanceEvaluation = attendanceEvaluations.FirstOrDefault(p => p.Date == theDay);
                //工时小于8小时非正常
                //todo: 抽出来这个判断非正常的逻辑
                if (attendanceEvaluation.Manhours < 80)
                {
                    isAbnormal = true;
                }
                // 获取正在提交中的评估修改申请

                var applyModifyStr = "";
                var modifyAttendanceApplication = modifyAttendanceApplications.FirstOrDefault(p => p != null && p.Date == theDay);
                var canApplyModify = (modifyAttendanceApplication == null);
                if (!canApplyModify && theDayInfo.Date != DateTime.Now.Date)
                {
                    applyModifyStr = "申请修改中";
                }


                var evaluationStatus = attendanceEvaluation.GetEvaluationStatusString();
                //是否是当天
                var isToday = false;
                if (theDay == DateTime.Now.Date)
                {
                    isToday = true;
                };
                var attendanceTheDayInfo = new
                {
                    theDay,
                    onDutyList =
                        attendanceInfoList.Where(
                            p => p.AttendanceType == AttendanceType.onDuty),
                    offDutyList =
                        attendanceInfoList.Where(
                            p => p.AttendanceType == AttendanceType.offDuty),
                    attendanceEvaluation.Manhours,
                    evaluationStatus,
                    leaveInfoModel,
                    canApplyModify,
                    isToday
                };

                var infoForCalendar = new
                {
                    theDayInfo,
                    isAbnormal,
                    evaluationStatus,
                    applyModifyStr
                };

                infoForCalendarList.Add(infoForCalendar);
                attendanceInfoPerDayList.Add(attendanceTheDayInfo);

            }
            monthAttendanceInfoList.Add(infoForCalendarList);
            monthAttendanceInfoList.Add(attendanceInfoPerDayList);

            return Json(monthAttendanceInfoList, JsonRequestBehavior.AllowGet);
        }


        //
        // POST: /Attendance/DoCheckAttendance
        [Authorize]
        public JsonResult DoCheckAttendance(string attendanceTypeStr, string explainText)
        {
            var attendanceType = EnumExt.ParseEnum<AttendanceType>(attendanceTypeStr);
            var userId = CurrentUserId;
            var dateTime = DateTime.Now;

            var statusInfo = AttendanceService.CheckAttendance(
                userId,
                dateTime,
                attendanceType,
                explainText
                );

            if (statusInfo.Status == ServiceStatus.Success)
            {
                if (attendanceType == AttendanceType.onDuty)
                {
                    statusInfo.Info = " OK! 您已经于 " + dateTime + " 完成上班考勤.  " + " 祝您一天工作愉快！";
                }
                else
                {
                    statusInfo.Info = " 辛苦了! 您已经于 " + dateTime + " 完成下班考勤. " + " 好好休息迎接新的一天！";
                }
            }

            //此次考勤已经正常完成
            return Json(statusInfo);
        }

        //
        // POST: /Attendance/DoApplyLeave

        [Authorize]
        public ActionResult DoApplyLeave(int dateTimeBegin, int dateTimeEnd, Guid leaveTypeId, string description)
        {
            var startTime = EpochDateTimeExtension.FromEpoch(dateTimeBegin);
            var endTime = EpochDateTimeExtension.FromEpoch(dateTimeEnd);
            var leaveTypeInfo = AttendanceService.GetLeaveTypeyById(leaveTypeId).Result;

            var newLeaveInfo = new LeaveInfo()
                                   {
                                       StartTime = startTime,
                                       EndTime = endTime,
                                       Description = description,
                                       LeaveTypeId = leaveTypeInfo.Id,
                                       LeaveTypeName = leaveTypeInfo.LeaveTypeName,
                                       UserId = CurrentUserId,
                                       IsAudited = false,
                                   };

            var statusInfo = AttendanceService.ApplyLeave(newLeaveInfo);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = "您已经申请了 " + leaveTypeInfo.LeaveTypeName + " 请等待审核。。";
            }

            return Json(statusInfo);
        }

        // 
        // POST: /Attendance/DoAuditLeave

        [Authorize]
        public ActionResult DoAuditLeave(Guid leaveInfoId, bool isAgreed, string auditNote)
        {
            var statusInfo = AttendanceService.AuditLeave(leaveInfoId, isAgreed, auditNote, CurrentUserId);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = "完成审批";
                statusInfo.Data = new { leaveId = leaveInfoId };
            }
            return Json(statusInfo);
        }



        /// <summary>
        /// 自动考勤的特殊方法
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="time"></param>
        /// <returns></returns>
        [Authorize]
        public JsonResult DoAutoCheckAttendance(Guid userId, int time)
        {
            StatusInfo statusInfo;
            try
            {
                var actionTime = EpochDateTimeExtension.FromEpoch(time);

                var defaultStatus = AttendanceService.GetDefaultAttendanceStatus(userId, actionTime).Result;
                if (defaultStatus.IsAbnormal)
                {
                    // 如果现在属于正常考勤，那么记录一次上班
                    throw new Exception(actionTime.ToString() + " 这个时间不是正常考勤时间，自动考勤无效");
                }
                if (defaultStatus.IsDuplicated)
                {
                    throw new Exception(actionTime.ToString() + " 这个时间重复考勤了");
                }
                statusInfo = AttendanceService.CheckAttendance(userId, actionTime, defaultStatus.AttendanceType,
                                                               "***门禁自动考勤***");
                if (statusInfo.Status == ServiceStatus.Success)
                {
                    statusInfo.Info = defaultStatus.AttendanceType.ToString();
                }
            }
            catch (Exception ex)
            {
                statusInfo = new StatusInfo(ex);
            }

            return Json(statusInfo, JsonRequestBehavior.AllowGet);
        }


        #endregion

        #region [ private method ]

        private DateTime getDateByDefault(long? time)
        {
            var date = DateTime.Now.Date;
            if (time.HasValue)
            {
                date = EpochDateTimeExtension.FromEpoch(time.Value);
            }
            return date;
        }

        private List<DayAttendanceInfoModel> findAttendanceInfoFromList(
            IEnumerable<AttendanceInfo> attendanceInfoList,
            DateTime theDay,
            AttendanceType? attendanceType = null,
            bool isAbnormal = false
            )
        {
            if (attendanceInfoList == null) throw new ArgumentNullException("attendanceInfoList");
            var query = attendanceInfoList.Where(p =>
                        p.Date.Day == theDay.Day &
                        p.IsAbnormalAttendance == isAbnormal
                    );
            if (attendanceType != null)
            {
                query = query.Where(
                    p => p.AttendanceType == attendanceType
                    );
            }
            var attendanceInfoOfTheDay = query.ToList();
            return convertAttendanceInfoToDayInfoToModel(attendanceInfoOfTheDay);
        }


        private static List<SimpleLeaveInfo> convertLeaveInfoListToSimpleModel(List<LeaveInfo> leaveInfoList)
        {
            var simpleLeaveInfoList = new List<SimpleLeaveInfo>();
            leaveInfoList.ForEach(
                p => simpleLeaveInfoList.Add(new SimpleLeaveInfo(p, AttendanceService))
                );
            return simpleLeaveInfoList;
        }


        private AttendanceStatus getDefaultAttendanceStatus()
        {
            return AttendanceService.GetDefaultAttendanceStatus(CurrentUserId, DateTime.Now).Result;
        }


        private List<DayAttendanceInfoModel> convertAttendanceInfoToDayInfoToModel(List<AttendanceInfo> attendanceInfoList)
        {
            var dayAttendanceInfoModel = new List<DayAttendanceInfoModel>();
            attendanceInfoList.ForEach(p => dayAttendanceInfoModel.Add(new DayAttendanceInfoModel(p)));
            return dayAttendanceInfoModel;
        }

        private static List<AttendanceInfoModel> convertAttendanceInfoListToModel(List<AttendanceInfo> attendanceInfoList)
        {
            var attendanceJsonModel = new List<AttendanceInfoModel>();
            attendanceInfoList.ForEach(p => attendanceJsonModel.Add(new AttendanceInfoModel(p)));
            return attendanceJsonModel;
        }



        private bool IsHasPermisson(String permissionStr, Guid userId)
        {
            var isHasPermisson = EzApiClient.UserHasPermission(permissionStr, userId);
            return isHasPermisson;
        }

        #endregion
    }

}
